"""
NetworkBreakerPlayer.py

Author: Miles Malerba
Date: 10-12-08
"""


from NetworkWaitFrame import NetworkWaitFrame
from Game import Game
from threading import Thread
from UndoCommand import UndoCommand
from MoveCommand import MoveCommand
import socket

class NetworkBreakerPlayer(Thread):
    """this class represents a networked breaker player.
       it acts as a proxy for a player on a remote machine.
    """

    def __init__(self, game, host, gui, waitTime):
        Thread.__init__(self)
        
        self.game = game
        self.host = host
        self.gui = gui
        self.waitTime = waitTime

        self.frame = None

        self.start()

    """Runs a thread waiting for input from
       the network breaker player"""
    def run(self):
        
        if (self.host == ""):
            #server
            #try:
            print "B1"
            server_sock = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
            server_sock.bind(('0.0.0.0', 1518))
            server_sock.listen(1)
            self.conn, addr_info = server_sock.accept()
            #except e:
                #print e
        else:
            #client
            #try:
            print "B2"
            client_sock = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
            client_sock.connect((self.host, 1527))
            self.conn = client_sock
            #except e:
                #print e
                
        self.game.register_observer(self)
        msg = None
        while 1:
            msg = self.conn.recv(1024)
            if (msg != None) :
                self.handleSocket(msg)
                msg = None

    """Deciphers the string returned by the coket
       and handles related command"""
    def handleSocket(self, msg):
        #Determines what type of move the
        #network player made

        #A breaker move
        if (msg[0] == 'g'):
            guess = [None,None,None,None]
            move = [None,None,None,None,None]
            move = self.input.split(' ')

            #loops index from 1-4
            for index in range(1, 5):
                if (move[index] == r):
                    self.guess[index-1] = 0
                if (move[index] == bl):
                    self.guess[index-1] = 1
                if (move[index] == g):
                    self.guess[index-1] = 2
                if (move[index] == y):
                    self.guess[index-1] = 3
                if (move[index] == w):
                    self.guess[index-1] = 4
                if (move[index] == bk):
                    self.guess[index-1] = 5

            breakerMove = BreakerMove(guess)

            if self.game.turn == self.game.BREAKER_TURN :
                self.moveCommand.execute(breakerMove)
            
        #A maker move is ignored.
        #if (self.input[0] == 'f'):           

        #Undo
        if (msg[0] == 'u'):
            self.undoCommand.execute()

        #A winner has been declared
        if (msg[0] == 'w'):
            self.winCommand.execute()

        #New game
        if (msg[0] == 'n'):
            self.newGameCommand.execute()

        #Exit game
        if (msg[0] == 'e'):
            self.exitCommand.execute()

    """Passes messages through the socket to the
       network player"""
    #Currently only passing moves and undo's are implemented
    def update(self, subject, param):
        
        if subject == game: 
            if param == Game.NOTIFY_MOVE:
                if self.game.turn == self.game.BREAKER_TURN : 
                    if self.frame == None:
                        self.frame = NetworkWaitFrame(self.gui.getRootInputView(),width=300, height=100)
                    self.sendCommand(self.game.get_last_move().get_network_string())
            elif param == Game.NOTIFY_UNDO:
                self.sendCommand('u')

    """handle if new game or exit command is executed"""
    def handleCommandExecuted(self, cmd):
        if cmd == 'exit':
            self.sendCommand('e')
        elif cmd == 'new':
            self.sendCommand('n')

    """send a command over the network"""
    def sendCommand(self, msg):
        self.conn.send(msg)
        
    def makeFirstMove(self, game):
            frame = NetworkWaitFrame(self.gui.getRootInputView(),width=300, height=100)
            self.gui.set_input_view(frame)
            self.sendCommand('g ')

    def setWaitTime(self, waitTime):
        self.waitTime = waitTime

    def setCommands(self, undoCommand, winCommand, moveCommand,
                    exitCommand, newGameCommand):
        self.moveCommand = moveCommand
        self.undoCommand = undoCommand
        self.winCommand = winCommand
        self.exitCommand = exitCommand
        self.newGameCommand = newGameCommand
 
